﻿package problems.cigarettesmokers;

import problems.BenchmarkSemaphore;


public class CigaretteSmokerSolution extends AbstractCigaretteSmokerSolution
{
    private BenchmarkSemaphore pusherMutex;
    private BenchmarkSemaphore smokerWithMatch;
    private BenchmarkSemaphore smokerWithPaper;
    private BenchmarkSemaphore smokerWithTobacco;

    private boolean isMatch;
    private boolean isPaper;
    private boolean isTobacco;

    public CigaretteSmokerSolution()
    {
        pusherMutex = new BenchmarkSemaphore(1);

        smokerWithTobacco = new BenchmarkSemaphore(0);
        smokerWithPaper = new BenchmarkSemaphore(0);
        smokerWithMatch = new BenchmarkSemaphore(0);
    }

    @Override
    public void pushTobacco()
    {
        getCreatedTobacco().waitOne();
        pusherMutex.waitOne();
        if (isPaper)
        {
            //Paper and tobacco => release the smoker with the match
            isPaper = false;
            smokerWithMatch.release();
        }
        else
        {
            if (isMatch)
            {
                //Match and tobacco => release the smoker with paper
                isMatch = false;
                smokerWithPaper.release();
            }
            else
            {
                //Just tobacco, no other ingrediënts received yet
                isTobacco = true;
            }
        }
        pusherMutex.release();
    }

    @Override
    public void pushPaper()
    {
        getCreatedPaper().waitOne();
        pusherMutex.waitOne();
        if (isTobacco)
        {
            //paper and tobacco => release the smoker with the match
            isTobacco = false;
            smokerWithMatch.release();
        }
        else
        {
            if (isMatch)
            {
                //paper and match => release the smoker with tobacco
                isMatch = false;
                smokerWithTobacco.release();
            }
            else
            {
                isPaper = true;
            }
        }
        pusherMutex.release();
    }

    @Override
    public void pushMatch()
    {
        getCreatedMatch().waitOne();
        pusherMutex.waitOne();
        if (isTobacco)
        {
            isTobacco = false;
            smokerWithPaper.release();
        }
        else
        {
            if (isPaper)
            {
                isPaper = false;
                smokerWithTobacco.release();
            }
            else
            {
                isMatch = true;
            }
        }
        pusherMutex.release();
    }

    @Override
    public void consumeResourcesAsSmokerWithMatch()
    {
        smokerWithMatch.waitOne();
        //make cigarette
        getAgentSemaphore().release();
        //smoke cigarette
    }

    @Override
    public void consumeResourcesAsSmokerWithTobacco()
    {
        smokerWithTobacco.waitOne();
        //make cigarette
        getAgentSemaphore().release();
        //smoke cigarette
    }

    @Override
    public void consumeResourcesAsSmokerWithPaper()
    {
        smokerWithPaper.waitOne();
        //make cigarette
        getAgentSemaphore().release();
        //smoke cigarette
    }

}